<?php

/**
 * winbinder 패키지 
 * 
 * 
 * @package php.ui.winbinder
 */

/**
 * 윈도우 생성 기본 클래스 
 *
 * @package php.ui.winbinder
 */ 
class WBWindow extends WBContainer { 

	private $_accelList = array();
	private $_rootPanel = null;
	private $_statusBar = null;
	private $_toolBar = null;
	private $_menu = null;
	private $_currentSplitter = null;
	private $_splitter = array();
	private $_capture = false; 
	private $_closed = true;

	public function __construct($options = array()) { 
		parent::__construct($options);
	}

	public function __destruct() { 
		parent::__destruct();
		
		unset($this->_accelList);
		unset($this->_rootPanel);
		unset($this->_statusBar);
		unset($this->_toolBar);
		unset($this->_menu);
		unset($this->_currentSplitter);
		unset($this->_splitter);
		unset($this->_capture);
		unset($this->_closed);
	}		
	
	protected function initCreate() { 
		parent::initCreate(); 

		$defaultStyle = WBC_INVISIBLE | WBC_NOTIFY | WBC_CUSTOMDRAW;
		$defaultParam = WBC_DBLCLICK | WBC_MOUSEMOVE | WBC_MOUSEDOWN | WBC_MOUSEUP | WBC_KEYDOWN | WBC_KEYUP | WBC_GETFOCUS | WBC_REDRAW | WBC_RESIZE | WBC_HEADERSEL ;

		$style = $this->getOption('style') | $defaultStyle;
		$param = $this->getOption('param') | $defaultParam;
		
		$this->setOption('style', $style);
		$this->setOption('param', $param);
		
		if (!isset($this->x)) $this->setOption('x', 0);
		if (!isset($this->y)) $this->setOption('y', 0);
		if (!isset($this->width)) $this->setOption('width', 80);
		if (!isset($this->height)) $this->setOption('height', 60);
		
		if (is_string($this->getOption('x'))) { $this->setOption('x', wbconstant($this->getOption('x'))); }
		if (is_string($this->getOption('y'))) { $this->setOption('y', wbconstant($this->getOption('y'))); }
		
	}

	protected function initEvent() { 
		parent::initEvent(); 

		// 이벤트 등록 
		$this->setEvent('show',			'onShow');
		$this->setEvent('hide',			'onHide');
		$this->setEvent('close',		'onClose');
		$this->setEvent('mousedown',	'onMouseDown');
		$this->setEvent('mousemove',	'onMouseMove');
		$this->setEvent('mouseup',		'onMouseUp');
		$this->setEvent('focus',		'onFocus');
		$this->setEvent('dblclick',		'onDoubleClick');
		$this->setEvent('active',		'onActive');
		$this->setEvent('accel',		'onAccel');
		$this->setEvent('dragstart',	'onDragStart');
		$this->setEvent('drag',			'onDrag');
		$this->setEvent('dragend',		'onDragEnd');
	}

	protected function initComponent() { 
		parent::initComponent();

		// 이벤트 핸들러 연결 
		$this->setHandler();

		// RootPanel 설정 
		$this->setRootPanel(new WBPanel(array('parent' => $this)));
		
		// 단축키 설정이 있을 때 
		if (isset($this->layout)) $this->setLayout($this->getOption('layout'));

		// 단축키 설정이 있을 때 
		if (isset($this->accel)) {
			$accel = $this->getOption('accel');
			$this->setAccel($accel[0], $accel[1]);
		}

		// menu, toolbar, statusbar 생성 
		if (isset($this->menu)) $this->setMenu($this->getOption('menu'));
		if (isset($this->toolbar)) $this->setToolBar($this->getOption('toolbar'));
		if (isset($this->statusbar)) $this->setStatusBar($this->getOption('statusbar'));

		if (isset($this->icon)) $this->setIcon($this->getOption('icon'));

		if (isset($this->controls)) { 
			foreach ($this->getOption('controls') as $control) { 
				$this->add($control);
			}
		}		
	}

	/**
	 * 발생한 이벤트 분기 함수 
	 * 
	 * @param int $window
	 * @param int $id
	 * @param int $ctrl
	 * @param int $param1
	 * @param int $param2
	 * @param int $param3
	 */
	public function handler($window, $id, $ctrl = 0, $param1 = 0, $param2 = 0, $param3 = 0) { 

		// 이벤트객체 (EventObject 생성 필요)
		$eventObject = new WBEvent($window, $id, $ctrl, $param1, $param2, $param3);

		switch($id) { 
		case IDCLOSE:			// 닫기 버튼 
		case IDDEFAULT:			 
			// 윈도우 메인 이벤트
			$this->fire($eventObject);
			break;
		default: 
			// component 이벤트 
			$obj = wbObject($id);
			
			if ($obj) { 
				$obj->fire($eventObject);
			} 
			//else { 
			//	$this->fireEvent('accel', $eventObject);
			//}

			break;

		}
		
		unset($eventObject);
			
	}
	
	public function setHandler() { 
		wb_set_handler($this->getInstance(), '__window_handler');
	}

	protected function createComponent() { 
		$instance = wb_create_window(
				WBApplication::getInstance($this->getOption('parent')), 
				$this->getOption('class'), 
				$this->getOption('title'), 
				$this->getOption('x'), 
				$this->getOption('y'), 
				$this->getOption('width'), 
				$this->getOption('height'),
				$this->getOption('style'),
				$this->getOption('param')
		);

		// 생성된 instance 전역변수로 설정 
		wbWindow($instance, $this);

		return $instance;
	}

	/**
	 * 윈도우 닫기 
	 * 
	 * 메모리 해제 
	 * 
	 */
	public function close() { 

		// 이벤트 실행 
		$this->fireEvent('close');
		
		if ($this->_closed) { 
			wb_destroy_window($this->getInstance());
		}
	}

	/**
	 * 하위 control 리스트 구하기 
	 * 
	 * @return array
	 */
	public function getChild() { 
		return $this->getItemList();
	}

	/**
	 * 창 최대화 
	 * 
	 */
	public function setMaximized() { 
		$this->setSize(WBC_MAXIMIZED, null);
	}

	/**
	 * 창 최소화 
	 * 
	 */
	public function setMinimized() { 
		$this->setSize(WBC_MINIMIZED, null);
	}

	/**
	 * 기존 크기로 복구 
	 * 
	 */
	public function setNormal() { 
		$this->setSize(WBC_NORMAL, null);
	}

	/**
	 * 최소화 여부 
	 * 
	 * @return bool
	 */
	public function isMinimized() { 
		return ($this->getSize() == WBC_MINIMIZED);
	}

	/**
	 * 최대화 여부 
	 * 
	 * @return bool
	 */
	public function isMaximized() { 
		return ($this->getSize() == WBC_MAXIMIZED);
	}

	/**
	 * 기존 크기 여부 
	 * 
	 * @return bool
	 */
	public function isNormal() { 
		return ($this->getSize() == WBC_NORMAL);
	}

	/**
	 * set window icon
	 * 
	 * @param resource|string $source
	 * @return bool
	 */
	public function setIcon($source) { 
		return $this->setImage($source);
	}

	/**
	 * get window title 
	 * 
	 * @return string
	 */
	public function getTitle() { 
		return $this->getText();
	}

	/**
	 * set window title 
	 * 
	 * @param string $title
	 */
	public function setTitle($title) { 
		$this->setText($title);
	}

	/**
	 * 딜레이 타임 설정 
	 * 
	 * 정해진 시간동안 이벤트 받기 대기 
	 * 
	 * @param int $pause 대기 시간 
	 * @param int $flags 특정 이벤트 지정 
	 * @return bool
	 */
	public function wait($pause = null, $flags = null) { 
		return wb_wait($this->getInstance(), $pause, $flags);
	}

	/**
	 * 단축키 설정 
	 * 
	 * @param int $id
	 * @param string $key 단축키
	 * @param callback $callback 콜백 함수 
	 */
	public function setAccel($id, $key, $callback = '') { 
		$this->_accelList[$id] = array('id' => $id, 'key' => $key, 'callback' => $callback);
	}

	/**
	 * 윈도우에 단축키 적용 
	 * 
	 */
	public function runAccel() { 
		new WBAccel(array(
			'parent' => $this->getInstance(), 
			'items' => $this->_accelList
		));
	}

	/**
	 * 최소 사이즈 설정 
	 * 
	 * @see WBComponent#setMinimumSize($width, $height)
	 */
	public function setMinimumSize($width = 0, $height = 0) {
		parent::setMinimumSize($width, $height);

		$this->setArea(WBC_MINSIZE, 0, 0, $width, $height);
	}

	/**
	 * 최대 사이즈 설정 
	 * 
	 * @see WBComponent#setMaximumSize($width, $height)
	 */
	public function setMaximumSize($width = 0, $height = 0) {
		parent::setMaximumSize($width, $height);

		$this->setArea(WBC_MAXSIZE, 0, 0, $width, $height);
	}

	/**
	 * 트레이 아이콘 여부 지정 
	 * 
	 * @param bool $isTaskBar true : 트레이 아이콘 지정 
	 */
	public function setTaskBar($isTaskBar = true) { 
		$this->setStyle(WBC_TASKBAR, $isTaskBar);
	}

	/**
	 * RootPanel 설정 
	 * 
	 * @param WBPanel $panel
	 */
	public function setRootPanel($panel) { 
		$this->_rootPanel = $panel; 
	}

	/**
	 * RootPanel 얻어오기 
	 * 
	 * @return WBPanel
	 */
	public function getRootPanel() { 
		return $this->_rootPanel;
	}

	/**
	 * 상태바 지정 
	 * 
	 * @param WBStatusBar $statusBar
	 * @return WBStatusBar
	 */
	public function setStatusBar($statusBar) { 
		$this->_statusBar = $statusBar;

		return $this->_statusBar;
	}

	/**
	 * 상태바 얻어오기 
	 * 
	 * @return WBStatusBar
	 */
	public function getStatusBar() { 
		return $this->_statusBar;
	}
	
	/**
	 * 상태바 자동 생성 
	 * 
	 * @param array $items
	 * @return WBStatusBar
	 */
	public function createStatusBar($options = array()) {
		
		$options['wbtype'] = 'StatusBar';
		
		$this->_statusBar = WBApplication::createObject($options, $this);
		
		return $this->_statusBar;
	}

	/**
	 * create ToolBar
	 * 
	 * @param array $options
	 * @return WBToolBar
	 */
	public function createToolBar($options = array()) { 
		$options['parent'] = $this;

		$this->_toolBar = new WBToolBar($options);
		
		return $this->_toolBar;
	}
	
	/**
	 * get created ToolBar
	 * 
	 * @return WBToolBar
	 */
	public function getToolBar() { 
		return $this->_toolBar;
	}

	/**
	 * 메뉴 생성
	 * 
	 * @param array $items
	 * @return WBMenu
	 */
	public function createMenu($items) { 
		$this->_menu = new WBMenu(array(
			'parent' => $this,
			'items'	 => $items,
		));

		return $this->_menu;
	}

	/**
	 * 메뉴 얻어오기 
	 * 
	 * @return WBMenu
	 */
	public function getMenu() { 
		return $this->_menu;
	}

	/**
	 * render layout 
	 * 
	 * 1. can run if _rootPanel exists
	 * 2. if toolbar created, _rootPanel change size and position  
	 * 
	 * @see WBContainer#doLayout()
	 */
	public function doLayout() { 

		if ($this->_rootPanel instanceof WBPanel) { 

			// get window size, position
			$size	= $this->getSize(true);
			$x = 0;
			$y = 0;
			
			// if toolbar exists
			if ($this->getToolBar()) { 
				$toolBarSize = $this->getToolBar()->getSize(true);
				
				$size['height'] -= $toolBarSize['height'];
				$y += $toolBarSize['height'];
			}
			
			if ($this->getStatusBar()) { 
				$statusBarSize = $this->getStatusBar()->getSize(true);
				
				$size['height'] -= $statusBarSize['height'];
			}

			$this->_rootPanel->setBounds($x, $y, $size['width'], $size['height'] );
		}
	}

	/**
	 * 이벤트 지정 
	 * 
	 * @see WBObject#fire($eo)
	 */
	public function fire($eo) { 
		// statusbar 객체 사이즈 변경 
		$this->fireStatusBarResize($eo);
		
		// split panel 실행
		$this->fireRenderSplitPanel($eo);
		
		if ($eo->isResize())	{ $this->fireEvent('resize', $eo);  return ; } 
		
		if ($eo->isMouseDown()) { 
			$this->fireEvent('mousedown', $eo);
			 
			if ($eo->isLeftButton()) { $this->fireEvent('dragstart', $eo); } // drag start event 		
			
			return ; 
		} 
		if ($eo->isMouseMove()) { 
			$this->fireEvent('mousemove', $eo);

			if ($eo->isLeftButton()) { $this->fireEvent('drag', $eo); }  // drag event						
			
			return ; 
		} 
		if ($eo->isMouseUp())	{ 
			$this->fireEvent('mouseup', $eo);
			 
			if ($eo->isLeftButton()) {  $this->fireEvent('dragend', $eo); 	}   // drag end event 
				
			return ; 
		}
		 
		if ($eo->isRedraw())	{ $this->fireEvent('redraw', $eo); return ; } 
		if ($eo->isFocus())		{ $this->fireEvent('focus', $eo); return ; } 
		if ($eo->isIDClose())	{ $this->close(); return; } 

	}
	
	public function onClose() { 
		$this->setClosed(true);
	}
	
	public function getClosed() { 
		return $this->_closed;
	}
	
	public function setClosed($closed = true) { 
		$this->_closed = $closed;
	}
	
	public function onRedraw($eo) { 
		$this->repaint($this->getGraphics($eo));
		
		// 패널에 전달 
		if ($this->_rootPanel instanceof WBPanel) { 
			$this->_rootPanel->fireEvent('redraw', $eo);
		}
	}
	
	public function fireStatusBarResize(WBEvent $eo) { 
		if ($this->_statusBar) {
			
			$size = $this->getSize(true);
		
			if ($this instanceof WBResizableWindow) { 
				$size['width'] -= 16;
			}				
			
			$statusbarSize = $this->_statusBar->getSize(true);
			$statusbarSize['width'] = $size['width'];
			
			$this->_statusBar->setSize($statusbarSize['width'], $statusbarSize['height']);
		}
	}

	/**
	 * Splitter Panel 에 이벤트 전파 
	 * 
	 * @param WBEvent $eo
	 * @return unknown_type
	 */
	public function fireRenderSplitPanel($eo) { 
	
		if ($eo->isMouseDown()) { 
			if ($eo->isLeftButton()) {
				$splitter = $this->getSplitter();
				
				foreach ($splitter as $temp) { 
					if ($temp->isArea($eo->x,$eo->y)) { // if current mouse pointer is splitter area
						$temp->setMousePosition($eo->x, $eo->y);
						$this->setCurrentSplitter($temp);
	
						$this->extern('SetCapture', $this);
						$this->_capture = true; 
	
						break;
										  
					}
				}
			}
		} else if ($eo->isMouseUp()) { 
			$this->extern('ReleaseCapture');
			$this->setCurrentSplitter(null);
			$this->_capture = false;			
		} else if ($eo->isMouseMove()) { 
			$splitter = $this->getCurrentSplitter();
			
			if ($splitter) { 
				if ($splitter->isArea($eo->x, $eo->y)) {
					if ($splitter->isEnabledMoveX()) { 
						$this->extern('SetMyCursor', WBUser::IDC_SIZEWE);
					} else { 
						$this->extern('SetMyCursor', WBUser::IDC_SIZENS);
					}
				} else { 
					$this->extern('SetMyCursor', WBUser::IDC_ARROW);
				}
			}
			
			if ($this->_capture) {
				if ($splitter) {
					if ($splitter->isEnabledMoveX()) { 
						$this->extern('SetMyCursor', WBUser::IDC_SIZEWE);
					} else { 
						$this->extern('SetMyCursor', WBUser::IDC_SIZENS);
					}				 
					$splitter->setMovePosition($eo->x, $eo->y);					  
				}
			}
		}
	}
	
	/**
	 * Window 에 컴포넌트 추가 
	 * 
	 * 실제로는 RootPanel 에 추가 
	 * 
	 * @see WBContainer#add($com)
	 */
	public function add($component) {
		if ($this->_rootPanel instanceof WBPanel) { 
			$com = wbCreate($component, $this);

			return $this->_rootPanel->add($com);
		}

		return $component;
	}
	
	public function setVisible($isVisible = true) { 
		parent::setVisible($isVisible);
		
		if ($this->_rootPanel instanceof WBPanel) { 
			$this->_rootPanel->setVisible($isVisible);
		}
	}

	/**
	 * 레이아웃 지정 
	 * 
	 * @see WBContainer#setLayout($layout)
	 */
	public function setLayout($layout) { 
		if ($this->_rootPanel instanceof WBPanel) { 
			$this->_rootPanel->setLayout($layout);
		}
	}

	/**
     * Timer 생성 
     * 
     * 기본 1초 기준 
	 *
	 * @param callback $callback 
	 * @param int $interval millisecond
	 */
	public function createTimer($callback, $interval = 1000) { 
		return new WBTimer(array(
			'parent'	=> $this,
			'interval'	=> $interval,
			'callback'	=> $callback,
		));
	}

	/**
	 * Timer 삭제 
	 * 
	 * @param WBTimer $timer
	 * @return bool
	 */
	public function destroyTimer($timer) { 
		return $timer->destroyTimer();
	}
	
	/**
	 * WBSplitter 추가 
	 * 
	 * @param WBSplitter $splitter
	 */
	public function addSplitter($splitter) { 
		$this->_splitter[] = $splitter;
	}
	
	/**
	 * WBSplitter 리스트 얻어오기 
	 * 
	 * @return array
	 */
	public function getSplitter() { 
		return $this->_splitter;		
	}

	/**
	 * 현재 선택된 Splitter 지정 
	 * 
	 * @param WBSplitter $splitter
	 */
	public function setCurrentSplitter($splitter) { 
		$this->_currentSplitter = $splitter;
	}
	
	/**
	 * 현재 선택된 Splitter 얻어오기 
	 * 
	 * @return WBSplitter
	 */
	public function getCurrentSplitter() { 
		return $this->_currentSplitter;
	}

}

function __window_handler($window, $id, $ctrl = 0, $param1 = 0, $param2 = 0, $param3 = 0) { 
	wbWindow($window)->handler($window, $id, $ctrl, $param1, $param2, $param3);
}

?>